use std::collections::HashMap;

use actix_web::{error, get, post, put, web, Error, HttpRequest, HttpResponse};
use datasource_connector::restful::{
    batch_instance_delete, batch_instance_query, get_instances, post_instance, put_instance,
};
use model_graph_types::{
    datasource::{
        DataSourceProvider, DeleteCondition, GetDataSourceOptions, QueryCondition, QueryExtention,
        QueryOptions, UpdateCondition,
    },
    modeling::system_meta_database,
};
use serde_json::json;

#[post("/ds/batch/delete")]
pub async fn ds_batch_delete(
    state: web::Data<crate::AppState>,
    request_obj: web::Json<Vec<(String, DeleteCondition)>>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let items = request_obj.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;

    let res = batch_instance_delete(
        context,
        &Some(meta_datasource),
        &default_datasource,
        items,
        None,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}

#[post("/ds/batch/insert")]
pub async fn ds_batch_insert(
    state: web::Data<crate::AppState>,
    request_obj: web::Json<Vec<(String, HashMap<String, serde_json::Value>)>>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let items = request_obj.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;
    let mut result: Vec<serde_json::Value> = vec![];
    for (s, c) in items {
        result.push(
            post_instance(
                context.clone(),
                &Some(meta_datasource.clone()),
                &default_datasource,
                &s,
                c,
                None,
            )
            .await
            .map_err(|err| error::ErrorInternalServerError(err))?,
        );
    }
    Ok(HttpResponse::Ok().json(json!(result)))
}

#[post("/ds/batch/update")]
pub async fn ds_batch_update(
    state: web::Data<crate::AppState>,
    request_obj: web::Json<Vec<(String, UpdateCondition, HashMap<String, serde_json::Value>)>>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let items = request_obj.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;

    let mut result: Vec<serde_json::Value> = vec![];
    for (s, c, e) in items {
        result.push(
            put_instance(
                context.clone(),
                &Some(meta_datasource.clone()),
                &default_datasource,
                &s,
                c,
                e,
                None,
            )
            .await
            .map_err(|err| error::ErrorInternalServerError(err))?,
        );
    }
    Ok(HttpResponse::Ok().json(json!(result)))
}

#[post("/ds/batch/find")]
pub async fn ds_batch_find(
    state: web::Data<crate::AppState>,
    request_obj: web::Json<Vec<(String, QueryCondition, Option<QueryExtention>)>>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let items = request_obj.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;

    let res = batch_instance_query(
        context,
        &Some(meta_datasource),
        &default_datasource,
        items,
        None,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}
